package com.example.resturant.service.impl;

import com.example.resturant.dto.SubmitOrderRequestDTO;
import com.example.resturant.model.Comment;
import com.example.resturant.model.Menu;
import com.example.resturant.model.Order;
import com.example.resturant.model.OrderMenu;
import com.example.resturant.repository.CommentRepository;
import com.example.resturant.repository.MenuRepository;
import com.example.resturant.repository.OrderMenuRepository;
import com.example.resturant.repository.OrderRepository;
import com.example.resturant.service.OrderService;
import com.example.resturant.vo.MenuVO;
import com.example.resturant.vo.OrderVO;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderRepository orderRepository;
    @Resource
    private OrderMenuRepository orderMenuRepository;
    @Resource
    private MenuRepository menuRepository;
    @Resource
    private CommentRepository commentRepository;

    @Override
    public Page<OrderVO> listOrders(Integer userId, Pageable page) {
        Page<Order> orders = orderRepository.findByUserId(userId, page);
        if (orders.isEmpty()) {
            return Page.empty(page);
        }
        List<Integer> orderIds = orders.stream().map(Order::getId).collect(Collectors.toList());
        List<OrderMenu> orderMenus = orderMenuRepository.findByOrderIdIn(orderIds);
        if (orderMenus.isEmpty()) {
            return Page.empty(page);
        }
        List<Integer> menuIds = orderMenus.stream().map(OrderMenu::getMenuId).collect(Collectors.toList());
        List<Menu> menus = menuRepository.findByIdIn(menuIds);
        Map<Integer, MenuVO> menuMap = menus.stream().collect(Collectors.toMap(Menu::getId, obj -> {
            MenuVO menuVO = new MenuVO();
            BeanUtils.copyProperties(obj, menuVO);
            return menuVO;
        }, (o, n) -> n));
        Map<Integer, List<MenuVO>> orderMenuMap = orderMenus.stream()
                .collect(Collectors.groupingBy(OrderMenu::getOrderId, Collectors.mapping(orderMenu -> {
                    MenuVO menuVO = menuMap.get(orderMenu.getMenuId());
                    menuVO.setQuantity(orderMenu.getQuantity());
                    return menuVO;
                }, Collectors.toList())));
        return orders.map(order -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            orderVO.setMenus(orderMenuMap.get(order.getId()));
            return orderVO;
        });
    }

    @Override
    @Transactional
    public void submit(Integer userId, SubmitOrderRequestDTO request) {
        Order order = new Order();
        order.setUserId(userId);
        order.setAddressId(request.getAddressId());
        order.setPrice(request.getTotalMoney());
        order.setGetType(request.getGetType());
        order.setGetTime(request.getGetTime());
        order.setLongTerm(request.getLongTerm());
        orderRepository.save(order);
        List<OrderMenu> orderMenus = request.getMenus().stream().map(menu -> {
            OrderMenu orderMenu = new OrderMenu();
            orderMenu.setOrderId(order.getId());
            orderMenu.setMenuId(menu.getProductId());
            orderMenu.setQuantity(menu.getQuantity());
            return orderMenu;
        }).collect(Collectors.toList());
        orderMenuRepository.saveAll(orderMenus);
    }

    @Override
    public void comment(Comment request) {
        Comment comment = commentRepository.findByOrderId(request.getOrderId());
        if (comment == null) {
            request.setDeleted(false);
            commentRepository.save(request);
            return;
        }
        comment.setComment(request.getComment());
        commentRepository.save(comment);
    }
}
